# -*- coding: utf-8 -*-

from django.db import models

class Country(models.Model):
    code = models.CharField(max_length=2,primary_key=True)
    name = models.CharField(max_length=16,unique=True)
    is_active = models.BooleanField(default=True)

    class Admin:
        list_display = ('code','name')


class City(models.Model):   #理论上主键应当是name + city，这里的特定场合下直接用name
    code = models.CharField(max_length=4,primary_key=True)
    name = models.CharField(max_length=16,unique = True)
    country = models.ForeignKey(Country)
    is_active = models.BooleanField(default=True)

    class Admin:
        list_display = ('code','name','country')

#交易所
class Exchange(models.Model):
    code = models.CharField(max_length=4,primary_key=True)    
    name = models.CharField(max_length=16,unique=True)
    city = models.ForeignKey(City)
    abbr_code = models.CharField(max_length=2,unique=True)    
    url = models.URLField(max_length=64,blank=True)
    is_active = models.BooleanField(default=True)

    class Admin:
        list_display = ('name','city','code','url')


#股票类型,如指数、基金、普通股票、权证等等
class StockType(models.Model):
    code = models.CharField(max_length=6,primary_key=True)
    name = models.CharField(max_length=16,unique=True)
    remark = models.CharField(max_length=256,blank=True)
    is_active = models.BooleanField(default=True)

    class Admin:
        list_display = ('name','remark')


#板块主题，如行业,地区,概念等,貌似也需要根据市场分类？或者从名称/code上区分？
class CatalogSubject(models.Model):
    name = models.CharField(max_length=16,primary_key=True)
    code = models.CharField(max_length=8,unique=True)
    remark = models.CharField(max_length=256,blank=True)
    is_active = models.BooleanField(default=True)

    class Admin:
        list_display = ('name','remark')


#板块
class Catalog(models.Model):
    name = models.CharField(max_length=16,unique=True)
    subject = models.ForeignKey(CatalogSubject,related_name='catalogs')
    remark = models.CharField(max_length=256,blank=True)
    is_active = models.BooleanField(default=True)

    class Admin:
        list_display = ('name','subject','remark')


#实体抽象
class AbsEntity(models.Model):
    remark = models.CharField(max_length=256,blank=True)
    is_active = models.BooleanField(default=True)
    last_modified = models.DateTimeField(auto_now = True)


    class Meta:
        abstract = True


#实体. 必须由id来作为代理主键，因为有可能更改名字
class Corporation(AbsEntity):
    name = models.CharField(max_length=64)
    ename = models.CharField(max_length=64,blank=True)
    address = models.CharField(max_length=64,blank=True)
    phone = models.CharField(max_length=32,blank=True)
    fax = models.CharField(max_length=32,blank=True)
    email = models.EmailField(blank=True)
    homepage = models.URLField(max_length=64,blank=True)

    class Admin:
        list_display = ('name','ename','address','homepage')


#代码. 为引用方便，用id为代理主键，实质主键是exchange + code.
class StockCode(AbsEntity):
    corporation = models.ForeignKey(Corporation)
    exchange = models.ForeignKey(Exchange)
    #为后续操作方便,code必须单独可区分(否则为了确定唯一stock,code和exchange必须一起出现,参数传递上复杂很多)
    #定义头两位为交易所简码，即存在code==>exchange的推导关系.
    code = models.CharField(max_length=8,unique=True)   
    name = models.CharField(max_length=16,blank=True)
    catalogs = models.ManyToManyField(Catalog,related_name='stocks')
    stype = models.ForeignKey(StockType)
    total_size = models.IntegerField(default=0)         #总股本
    outstanding_size = models.IntegerField(default=0)   #流通股，这里没有区分A/B/H，因为不同的形态其code不同，所以只需要保存当前形态的流通股数

    class Admin:
        list_display = ('code','name','stype','corporation','exchange')

    class Meta:
        pass


#代码更名历史，只在更名或者股本变化时更新
class StockCodeHistory(models.Model):
    scode = models.ForeignKey(StockCode)
    name = models.CharField(max_length=16)
    remark = models.CharField(max_length=256,blank=True)
    enable_date = models.DateField(auto_now_add = True) #启用时间
    total_size = models.IntegerField(default=0)         #总股本
    outstanding_size = models.IntegerField(default=0)   #流通股，这里没有区分A/B/H，因为不同的形态其code不同，所以只需要保存当前形态的流通股数

    class Admin:
        list_display = ('scode','name','enable_date','remark')



#数据来源. 设立数据来源的原因在于新股票添加的非同步性. 所以新增原始行情数据必须以数据来源的代码保存，当股票名添加成功后，才有可能转化到整理后数据中
#另一点，不同数据来源数据的互相印证，也需要区分数据来源
class Source(Corporation):
    quote_url = models.URLField(max_length=64,blank = True) #行情数据
    x_url = models.URLField(max_length=64,blank = True)     #除权数据
    report_url = models.URLField(max_length=64,blank = True)    #年报/季报数据
    finance_url = models.URLField(max_length=64,blank = True)   #财务数据
    is_realtime = models.BooleanField(default=False)

    class Admin:
        list_display = ('name','ename','address','homepage')


class Mapping(models.Model):    #这个表根据源相关的代码表更新. 应当弱化. 源读取器读取时应当做好代码的转换.只有在没有规则的时候才由读取器来根据这个mapping解决问题
    source = models.ForeignKey(Source)
    source_code = models.CharField(max_length=16)
    standard = models.ForeignKey(StockCode)
    create_date = models.DateField(auto_now_add=True)

    class Meta:
        unique_together = (('source','source_code'),('source','standard'))
        #一个股票在一个数据源中只有一个对应的源的代码

    class Admin:
        pass


#交易日历. 其中month_num/week_num从1800年起
class TransCalendar(models.Model):
    tdate = models.IntegerField(primary_key=True)
    month_num = models.IntegerField()   #用yyyymm表示
    month_day = models.IntegerField()   
    week_num = models.IntegerField()    #用yyyyww表示
    week_day = models.IntegerField()
    
    class Admin:
        pass


#日行情
class DayQuote(models.Model):
    topen = models.IntegerField(default=0)      #单位为0.1分
    tclose = models.IntegerField(default=0)     #单位为0.1分
    thigh = models.IntegerField(default=0)      #单位为0.1分
    tlow = models.IntegerField(default=0)       #单位为0.1分
    tavg = models.IntegerField(default=0)       #单位为0.1分
    tamount = models.IntegerField(default=0)    #单位为百元
    tvolume = models.IntegerField(default=0)    #单位为手

    class Meta:
        abstract = True


class SDayQuote(DayQuote):  #本表须手工创建，虚化id,而将主键设在source,sstock,tdate上
    #source = models.ForeignKey(Source)  #这块应该适当弱化. 
    sstock = models.CharField(max_length=8)    #与Mapping中的source_code对应，但可能不存在对应物. 原则上已经应当是现行的标准code或将来必然的标准code,由读取器解决
    tdate = models.IntegerField()
    
    class Admin:
        pass

    class Meta:
        unique_together = ('sstock','tdate')

        
class XDayQuote(DayQuote):  #本表须手工创建，虚化id,而将主键设在tstock,tdate上
    tstock = models.ForeignKey(StockCode)
    tdate = models.IntegerField()

    class Admin:
        pass

    class Meta:
        unique_together = ('tstock','tdate')


class SHourQuote(DayQuote):  #本表须手工创建，虚化id,而将主键设在source,sstock,tdate上
    #source = models.ForeignKey(Source)  #这块应该适当弱化. 
    sstock = models.CharField(max_length=8)    #与Mapping中的source_code对应，但可能不存在对应物. 原则上已经应当是现行的标准code或将来必然的标准code,由读取器解决
    tdate = models.IntegerField()
    
    class Admin:
        pass

    class Meta:
        unique_together = ('sstock','tdate')

        
class XHourQuote(DayQuote):  #本表须手工创建，虚化id,而将主键设在tstock,tdate上
    tstock = models.ForeignKey(StockCode)
    tdate = models.IntegerField()

    class Admin:
        pass

    class Meta:
        unique_together = ('tstock','tdate')


class PowerInfo(models.Model): #本表须手工创建，虚化id,而将主键设在tstock,tdate上
    STATE_CHOICES = ((0,'not apply'),(1,'applied'))
    tstock = models.ForeignKey(StockCode)
    sgbl = models.IntegerField(default=0)   #以1/1000为比例
    pgbl = models.IntegerField(default=0)   #以1/1000为比例
    pgj = models.IntegerField(default=0)    #单位为0.1分
    fhbl = models.IntegerField(default=0)   #单位为0.1分
    zfs = models.IntegerField(default=0)    #单位为万股
    zfj = models.IntegerField(default=0)    #单位为万股
    jjs = models.IntegerField(default=0)    #解禁数,单位为万股
    register_day = models.IntegerField()
    execute_day = models.IntegerField()
    #state = models.IntegerField(choices=STATE_CHOICES,default=0)   #日线除权状态
    day_state = models.IntegerField(choices=STATE_CHOICES,default=0)   #日线除权状态
    hour_state = models.IntegerField(choices=STATE_CHOICES,default=0)   #小时除权状态
    m5_state = models.IntegerField(choices=STATE_CHOICES,default=0)  #5分钟线除权状态

    class Admin:
        pass

    class Meta:
        unique_together = ('tstock','execute_day')


class Report(models.Model): #本表须手工创建，虚化id,而将主键设在tstock,tyear,tperiod上
    tstock = models.ForeignKey(StockCode)
    announce_day = models.IntegerField()
    tperiod = models.IntegerField()  #报告期yyyymm,mm两位1-12表示1,2,一季,4,5,半年,7,8,三季,10,11,年报
    zgb = models.IntegerField()      #单位为万股   
    ag = models.IntegerField()       #单位为万股   
    bg = models.IntegerField()       #单位为万股      
    hg = models.IntegerField()       #单位为万股   
    mgwfplr = models.IntegerField()  #单位为0.1分
    mggjj = models.IntegerField()    #单位为0.1分
    mgjzc = models.IntegerField()    #单位为0.1分
    mgsy = models.IntegerField()     #单位为0.1分   

    class Admin:
        pass

    class Meta:
        unique_together = ('tstock','tperiod')


#log放入到django_admin_log中

